package com.qf.common.aop.annotation.impl;


import com.auth0.jwt.interfaces.DecodedJWT;
import com.qf.common.aop.annotation.LoginUser;
import com.qf.common.constant.RabbitMqConstants;
import com.qf.common.utils.JwtUtils;
import com.qf.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;

@Component
@Aspect
public class LoginUserAopImpl {
//    @Around("@annotation(loginUser)")
    //解析token的方法,有LoginUser注解的方法会调用这个方法来解析token
    @Around("@annotation(loginUser)")
    public Object parse(ProceedingJoinPoint proceedingJoinPoint, LoginUser loginUser) throws Throwable {
        System.out.println("LoginUserAopImpl.parse");
        // 如果用autowired自动注入存在线程安全问题,先获取HttpServeltRequest对象
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        //获取请求头中的token
        String token = request.getHeader(RabbitMqConstants.LOGIN_TOKEN);
        //判断token是否为空
        User user = null;
        if (!StringUtils.isEmpty(token)) {
            //校验
            DecodedJWT decodedJWT = JwtUtils.checkToken(token);
            //token中获取 user信息
            String id = JwtUtils.getWithClaim("id", decodedJWT);
            String username = JwtUtils.getWithClaim("username", decodedJWT);
            //封装
            user = new User();
            user.setId(Integer.parseInt(id));
            user.setUsername(username);


        }//获取当前请求传递的参数,获取Controller方法上的参数
        Object[] args = proceedingJoinPoint.getArgs();
        //从args中找到user对象的,因为传的参数不止是user
        for (int i = 0; i < args.length; i++) {
            // 如果是user类型，把args中的user对象替换我们自己封装的
            if (args[i] instanceof User) {
                args[i] = user;
                break;
            }
        }

        // 调用目标方法
        // 因为我们替换了目标方法的参数，所以这里一定要传递下去
        return proceedingJoinPoint.proceed(args);
    }

}